package com.tanjie.blackbean.web.advice;

import com.tanjie.blackbean.web.annotation.BlackBeanController;
import com.tanjie.blackbean.web.annotation.WrapResponse;
import com.tanjie.blackbean.pojo.response.ResponseBean;
import com.tanjie.blackbean.web.support.AnnotationExtractor;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;

/**
 * api接口响应统一格式封装
 *
 * @author: tanjie
 * @date: 2022-03-30
 **/
@Slf4j
@RestControllerAdvice
public class WrapResponseAdvice implements ResponseBodyAdvice<Object> {

    /**
     * 返回true就会调用下面的beforeBodyWrite方法
     */
    @Override
    public boolean supports(MethodParameter returnType,
                            @Nullable Class<? extends HttpMessageConverter<?>> converterType) {
        Method method = returnType.getMethod();
        if (method != null) {
            Class<?> methodReturnType = method.getReturnType();
            // 不支持返回类型为String
            if (String.class.isAssignableFrom(methodReturnType)) {
                return false;
            }
            // 如果已经手动封装了，就不用再封装一层了
            if (ResponseBean.class.isAssignableFrom(methodReturnType)) {
                return false;
            }
        }
        // 跳过feign
        BlackBeanController blackBeanController = AnnotationExtractor.get(returnType, BlackBeanController.class);
        if (blackBeanController != null) {
            if (blackBeanController.isFeign()) {
                return false;
            }
        }
        // 基于注解开启功能
        WrapResponse wrapResponse = AnnotationExtractor.get(returnType, WrapResponse.class);
        boolean support = wrapResponse != null && wrapResponse.enable();
        if (support) {
            // 返回值为void是否封装
            if (method != null && method.getReturnType().getName().equals("void")) {
                return wrapResponse.wrapIfEmpty();
            }
        }
        return support;
    }

    @Override
    public Object beforeBodyWrite(Object body,
                                  @NonNull MethodParameter returnType,
                                  @NonNull MediaType selectedContentType,
                                  @NonNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  @NonNull ServerHttpRequest request,
                                  @NonNull ServerHttpResponse response) {
        // 获取注解
        WrapResponse wrapResponse = AnnotationExtractor.get(returnType, WrapResponse.class);
        if (wrapResponse == null) {
            return body;
        }
        // 从注解中获取响应数据格式类
        Class<? extends ResponseBean> resultType = wrapResponse.responseType();
        try {
            ResponseBean responseBean = resultType.newInstance();
            return responseBean.success(body);
        } catch (Exception e) {
            e.printStackTrace();
            return body;
        }
    }


}
